// ==UserScript==
// @name				[PHPhulp] UBBBar PHP add-on
// @namespace		http://phphulp.ikhoefgeen.nl/ubb
// @description	UBB-balk met sneltoetsen
// @include			http://*.phphulp.nl/*
// @include			http://phphulp.nl/*
// @include			http://phphulp.ikhoefgeen.nl/ubb/*
// ==/UserScript==

(function() {

var RESOURCES 	= 'http://phphulp.ikhoefgeen.nl/ubb/revisited/Resources';
//var SCRIPTS 	= 'http://phphulp.ikhoefgeen.nl/ubb/revisited/Scripts';
var SCRIPTS = './Scripts';

var _IHGOnload = window.IHGOnload || function() {};
window.IHGOnload = function(IHG)
{
	var patch = IHG.patch;
	
	
	IHG.LookupWindow = function(backendURI)
	{
		var _self = this;
		this.width = 250;
		this.backendURI = backendURI;
		this.gui = {
			window: 			patch(document.createElement('div')),
			searchField: 	patch(document.createElement('input')),
			resultsList: 	patch(document.createElement('div')),
			cancelButton: 	patch(document.createElement('input'))
		}
		
		with(this.gui) {
			with(this.gui.cancelButton) {
				type = 'button';
				value = 'Annuleren';
				style.cssFloat = 'right';
				this.gui.cancelButton.on('click', function() {
					_self.close();
				});
			}
			
			with(this.gui.resultsList) {
				style.width = '100%';
				style.height = '200px';
				style.overflow = 'auto';
				style.overflowX = 'hidden';
			}
			
			with(this.gui.searchField) {
				type = 'text';
				style.width = '244px';
				style.border = '1px solid silver';
				style.margin = '2px';
				style.padding = '2px';
				this.gui.searchField.on('keypress', function(e) {
					if(_self.handleControlKeys(e.keyCode)) {
						return false;
					}
					
					_self.lookup(_self.gui.searchField.value);
				});
			}
			
			with(this.gui.window.style) {
				background = 'white';
				display = 'none';
				position = 'absolute';
				width = this.width;
				height = '250px';
				border = '1px solid silver';
				borderTop = '0';
				top = 0;
				left = 0;
				font = '11px Verdana';
			}
			
			window.appendChild(searchField);
			window.appendChild(resultsList);
			window.appendChild(cancelButton);
		}
		
		document.body.appendChild(this.gui.window);
	}
	
	IHG.LookupWindow.prototype = {
		open: function(sender, callback, closeCallback)
		{
			var _self = this;
			var senderPosition = sender.position();
			with(this.gui.window.style) {
				display = 'block';
				top = senderPosition.y + 'px';
				left = senderPosition.x + ((sender.txtarea.clientWidth - this.width) / 2) + 'px';
			}
			
			this.closeCallback = closeCallback;
			
			if(callback) {
				this.gui.searchField.on('keypress', function(e) {
					if(_self.handleControlKeys(e.keyCode)) {
						return false;
					}
					
					if(_self._lookupTimeout) {
						clearTimeout(_self._lookupTimeout);
					}
					
					_self._lookupTimeout = setTimeout(function() {
						_self.lookup(_self.gui.searchField.value, callback);
					}, 100);
				});
			}
					
			setTimeout(function() {
				_self.gui.searchField.focus();
			}, 10);
		},
		
		close: function()
		{
			with(this.gui) {
				window.style.display = 'none';
				searchField.value = '';
			}
			
			if(this.closeCallback) {
				this.closeCallback();
			}
		},
		
		lookup: function(query, callback)
		{
			var _self = this;
			if(query.length < 3) return;
			
			if(this._lastQuery && query.substr(0, this._lastQuery.query.length) == this._lastQuery.query) {
				this._lastQuery.filteredQuery = query;
				var filtered = [];
				for(var i = 0; i < this._lastQuery.results.length; i++) {
					var result = this._lastQuery.results[i];
					if(result.value.match(query)) {
						filtered.push(result);
					}
				}
				this.showResults(filtered, callback);
			} else {
				_self._lastQuery = {
					query: query,
					results: [],
					filteredQuery: query,
					callback: callback
				}
								
				this.startLoading();
				
				IHG.JSONRequest(this.backendURI.replace(/\*/, query), function(results) {
					_self._lastQuery.results = results;
					_self.lookup(_self._lastQuery.filteredQuery, _self._lastQuery.callback);
					_self.stopLoading();
				});
			}
		},
		
		showResults: function(results)
		{
			var _self = this;
			this._activeResultNode = null;
			
			this.gui.resultsList.innerHTML = '';
			
			var highlightPattern = this._lastQuery.filteredQuery;
			var replacementPattern = '<span style="background: yellow;">' + this._lastQuery.filteredQuery + '</span>';
			
			for(var i = 0; i < results.length; i++) {
				var result = results[i];
				var resultNode = patch(document.createElement('div'));
				with(resultNode.style) {
					cursor = 'pointer';
					padding = '5px 2px';
				}
				this.gui.resultsList.appendChild(resultNode);
				resultNode.innerHTML = '\
					<span style="font-size: 13px;display: block">' + result.value.replace(highlightPattern, replacementPattern) + '</span>\
					<span style="color: grey">' + result.hint + '</span>';
				
				resultNode.on('mouseover', function(node, result) {
					return function() {
						if(_self._activeResultNode) {
							_self._activeResultNode.fire('mouseout');
						}
						
						_self._activeResultNode = node;
						node.style.backgroundColor = 'blue';
					}
				}(resultNode, result));
				
				resultNode.on('mouseout', function(node) {
					return function() {
						node.style.backgroundColor = 'transparent';
					}
				}(resultNode));
				
				resultNode.on('click', function(result) {
					return function() {
						_self._lastQuery.callback(result);
					}
				}(result));
			}
		},
		
		handleControlKeys: function(keyCode)
		{
			if(keyCode == 38 || keyCode == 40) {
				if(!this._activeResultNode) {
					if(this.gui.resultsList.firstChild) {
						this.gui.resultsList.firstChild.fire('mouseover');
					}
				} else {
					var newActiveResultNode = this._activeResultNode[keyCode == 38 ? 'previousSibling' : 'nextSibling'];
					if(newActiveResultNode) {
						newActiveResultNode.fire('mouseover');
						newActiveResultNode.parentNode.scrollTop = newActiveResultNode.offsetTop - 100;
					}
				}
			} else if(keyCode == 13) {
				if(this._activeResultNode) {
					this._activeResultNode.fire('click');
				}
			} else if(keyCode == 27)  {
				this.close();
			} else {
				return false;
			}
			
			return true;
		},
		
		startLoading: function()
		{
			this.gui.searchField.style.background = 'inherit url(' + RESOURCES + '/loading.gif) 220px 3px no-repeat';
		},
		
		stopLoading: function()
		{
			this.gui.searchField.style.background = '';
		}
	}
	
	var functionLookup  = new IHG.LookupWindow(SCRIPTS + '/function_lookup.php?query=*');
	
	with(IHG.Toolbar) {
		Default.addButton(new Button({
				id: 'nl.ikhoefgeen.phphulp.phplookup',
			label: 'PHP functie invoegen',
			image: RESOURCES + '/php.png',
			shortcut: Keys.CMD + 'o', // todo
			action: function(sender) {
				with(sender.selectionController) {
					if(this.state == DISABLED)
						return;
					
					if(!isWrapped('[php]', '[/php]')) {
						if(selectionLength() == 0) {
							functionLookup.open(sender, 
								function(result)
								{
									if(isMarked('[code]', '[/code]') || isMarked('<?php', '?>')) {
										wrap(result.value + '(', ')');
									} else {
										wrap('[php]' + result.value + '[/php]', '');
									}
									functionLookup.close();
								},
								function()
								{
									sender.txtarea.focus()
								});
						} else {
							wrap('[php]', '[/php]');
						}
					} else {
						unwrap('[php]', '[/php]');
					}
				}
			},
			condition: function(sender) {
				with(sender.selectionController) {					
					if(isMarked('[img]', '[/img]')) {
						this.state = DISABLED;
					} else if(isMarked('[php]', '[/php]')) {
						this.state = ACTIVE;
					} else {
						this.state = ENABLED;
					}
				}
			}
		}));
	}
	
	window.IHGOnload = null;
}

if(window.IHG) {
	window.IHGOnload(window.IHG);
}

})();